home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / powervww / pvdrv.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-05  |  28.2 KB  |  1,187 lines

  1. //  ____________________________________________________
  2. // |                                                    |
  3. // |  Project:     POWER VIEW INTERFACE                 |
  4. // |  File:        PVDRV.CPP                            |
  5. // |  Compiler:    WPP386 (10.6)                        |
  6. // |                                                    |
  7. // |  Subject:     Drivers implementation               |
  8. // |                                                    |
  9. // |  Author:      Emil Dotchevski                      |
  10. // |____________________________________________________|
  11. //
  12. // E-mail: zajo@geocities.com
  13. // URL:    http://www.geocities.com/SiliconValley/Bay/3577
  14.  
  15. #define uses_conio
  16. #define uses_ctype
  17. #define uses_string
  18. #define uses_comlin
  19. #define uses_config
  20. #define uses_ini
  21. #define uses_system
  22.  
  23. #define DECLARE_PVDRV
  24. #include "PVuses.h"
  25. #undef DECLARE_PVDRV
  26.  
  27. #pragma off( check_stack )
  28.  
  29.  
  30. /*
  31. EVENTS DRIVER
  32. */
  33.   struct Tevents_data
  34.   {
  35.     boolean events_overflow_flag;
  36.     uint event_mask;
  37.     uint events_num;
  38.     unsigned long old_timer;
  39.     Tevent events_queue[MAX_EVENTS];
  40.   };
  41.  
  42.   static Tevents_data events_data =
  43.   {
  44.   /* EVENTS_OVERFLOW_FLAG */ 0,
  45.   /* EVENT_MASK           */ (uint)-1
  46.   #ifndef NOMOUSE
  47.                                     & ~evMOUSE_MOVE
  48.   #endif
  49.   ,
  50.   /* EVENTS_NUM           */ 0,
  51.   /* OLD_TIMER            */
  52.   /* EVENTS_QUEUE         */
  53.   };
  54.  
  55.   #define EVENTS_OVERFLOW_FLAG events_data.events_overflow_flag
  56.   #define EVENT_MASK events_data.event_mask
  57.   #define EVENTS_NUM events_data.events_num
  58.   #define OLD_TIMER events_data.old_timer
  59.   #define EVENTS_QUEUE events_data.events_queue
  60.  
  61.   uint get_system_events_mask( void )
  62.   {
  63.     return EVENT_MASK;
  64.   };
  65.  
  66.   void set_system_events_mask( uint em )
  67.   {
  68.     EVENT_MASK = em;
  69.   };
  70.  
  71.   void clear_events( void )
  72.   {
  73.     Tevent ev;
  74.     while( EVENTS_NUM ) get_event( ev );
  75.   };
  76.  
  77.   boolean event_present( void )
  78.   {
  79.     return ( EVENTS_NUM != 0 );
  80.   }
  81.  
  82.   #ifdef __386__
  83.   //Dummy function to indicate org of the code to lock
  84.   void events_lock_region_begin( void )
  85.   {
  86.   }
  87.   #endif
  88.  
  89.   extern char _cld( void );
  90.   #pragma aux _cld = "cld";
  91.  
  92.   extern char set_es( void );
  93.   #pragma aux set_es = \
  94.     "mov ax,ds"        \
  95.     "mov es,ax"        \
  96.     modify [ax];
  97.  
  98.   boolean put_event( Tevent &ev )
  99.   {
  100.     set_es();
  101.     if( !( ev.code & EVENT_MASK ) ) return 0;
  102.     if( ( EVENTS_OVERFLOW_FLAG = ( EVENTS_NUM == MAX_EVENTS ) ) != 0 )
  103.     {
  104.       smart_beep( 1000, 1 );
  105.       return 0;
  106.     }
  107.     _cli();
  108.     EVENTS_QUEUE[EVENTS_NUM++] = ev;
  109.     _sti();
  110.     return 1;
  111.   };
  112.  
  113.   #ifdef __386__
  114.   //Dummy function to indicate end of the code to lock
  115.   void events_lock_region_end( void )
  116.   {
  117.   }
  118.   #endif
  119.  
  120.   void get_event( Tevent &ev )
  121.   {
  122.     static boolean first_idle = 1;
  123.     unsigned long timer;
  124.   #ifdef __FLAT__
  125.     unsigned long *system_timer = (unsigned long *) BIOS_DTA( 0x6C );
  126.     timer = *system_timer;
  127.   #else
  128.     unsigned long far *system_timer = (unsigned long *) BIOS_DTA( 0x6C );
  129.     do { timer = *system_timer; } while( timer!=*system_timer );
  130.   #endif
  131.     uint i, j, p;
  132.  
  133.     if( !EVENTS_NUM )
  134.     {
  135.       ev.code = evNOTHING;
  136.       ev.priority = 0;
  137.       ev.destination = NULL;
  138.       if( first_idle ) OLD_TIMER = timer;
  139.       first_idle = 0;
  140.       ev.TIME_PASSED = timer - OLD_TIMER;
  141.       return;
  142.     }
  143.     first_idle = 1;
  144.     _cli();
  145.     for( i = 0, p = (uint)-1; i < EVENTS_NUM; i++ )
  146.       if( EVENTS_QUEUE[i].priority < p )
  147.       {
  148.         p = EVENTS_QUEUE[i].priority;
  149.         j = i;
  150.       }
  151.     memcpy( &ev, &EVENTS_QUEUE[j], sizeof( Tevent ) );
  152.     memmove( &EVENTS_QUEUE[j], &EVENTS_QUEUE[j+1],
  153.              ( --EVENTS_NUM - j ) * sizeof( Tevent ) );
  154.     _sti();
  155.   }
  156.  
  157.   boolean events_overflow( void )
  158.   {
  159.     return EVENTS_OVERFLOW_FLAG;
  160.   }
  161.  
  162.  
  163. /*
  164. TIMER DRIVER
  165. */
  166.   #define MAX_TIMERS 16
  167.   #define TIMER_INTR  8//0x1C
  168.  
  169.   struct Ttimer_data
  170.   {
  171.     uint allocs;
  172.     uint counters[MAX_TIMERS];
  173.     Tcallback callbacks[MAX_TIMERS];
  174.     Tevent events[MAX_TIMERS];
  175.     void (interrupt far *old_timer_handler )( void );
  176.   };
  177.  
  178.   static Ttimer_data timer_data;
  179.  
  180.   #define ALLOCS timer_data.allocs
  181.   #define COUNTERS timer_data.counters
  182.   #define CALLBACKS timer_data.callbacks
  183.   #define EVENTS timer_data.events
  184.   #define OLD_TIMER_HANDLER timer_data.old_timer_handler
  185.  
  186.   #ifdef __386__
  187.   //Dummy function to indicate org of the code to lock
  188.   void timer_lock_region_begin( void )
  189.   {
  190.   }
  191.   #endif
  192.  
  193.   static void _loadds interrupt far timer_handler( void )
  194.   {
  195.     set_es();
  196.     for( int i=0; i<MAX_TIMERS; i++ )
  197.       if( COUNTERS[i]>0 && !--COUNTERS[i] )
  198.         if( CALLBACKS[i] != NULL )
  199.           CALLBACKS[i]();
  200.         else
  201.           put_event( EVENTS[i] );
  202.     OLD_TIMER_HANDLER();
  203.   }
  204.  
  205.   #ifdef __386__
  206.   //Dummy function to indicate end of the code to lock
  207.   void timer_lock_region_end( void )
  208.   {
  209.   }
  210.   #endif
  211.  
  212.   int alloc_timer( void )
  213.   {
  214.     int i;
  215.     uint u;
  216.     for( i=0,u=1; i<MAX_TIMERS; i++,u<<=1 )
  217.       if( !(ALLOCS&u) )
  218.       {
  219.         ALLOCS |= u;
  220.         return i;
  221.       }
  222.     return -1;
  223.   }
  224.  
  225.   void event_request( int handle, Tevent &ev, uint ticks )
  226.   {
  227.     if( handle==-1 ) return;
  228.     CALLBACKS[handle] = NULL;
  229.     memcpy( &EVENTS[handle], &ev, sizeof( Tevent ) );
  230.     COUNTERS[handle] = ticks;
  231.   }
  232.  
  233.   void call_request( int handle, Tcallback callback, uint ticks )
  234.   {
  235.     if( handle==-1 ) return;
  236.     CALLBACKS[handle] = callback;
  237.     COUNTERS[handle] = ticks;
  238.   }
  239.  
  240.   void cancel_request( int handle )
  241.   {
  242.     if( handle==-1 ) return;
  243.     COUNTERS[handle] = 0;
  244.   }
  245.  
  246.   void free_timer( int handle )
  247.   {
  248.     int i;
  249.     uint u;
  250.     if( handle==-1 ) return;
  251.     cancel_request( handle );
  252.     for( i=0,u=1; i<handle; i++,u<<=1 );
  253.     ALLOCS &= ~u;
  254.   }
  255.  
  256.  
  257. /*
  258. KEYBOARD DRIVER
  259. */
  260.   #define KBD_INTR 0x09
  261.  
  262.   static char convert_table[] = {
  263.     (kALT_A >> 8), (kALT_B >> 8), (kALT_C >> 8), (kALT_D >> 8), (kALT_E >> 8),
  264.     (kALT_F >> 8), (kALT_G >> 8), (kALT_H >> 8), (kALT_I >> 8), (kALT_J >> 8),
  265.     (kALT_K >> 8), (kALT_L >> 8), (kALT_M >> 8), (kALT_N >> 8), (kALT_O >> 8),
  266.     (kALT_P >> 8), (kALT_Q >> 8), (kALT_R >> 8), (kALT_S >> 8), (kALT_T >> 8),
  267.     (kALT_U >> 8), (kALT_V >> 8), (kALT_W >> 8), (kALT_X >> 8), (kALT_Y >> 8),
  268.     (kALT_Z >> 8)
  269.   };
  270.   static char num_convert_table[] = {
  271.     (kALT_0 >> 8), (kALT_1 >> 8), (kALT_2 >> 8), (kALT_3 >> 8), (kALT_4 >> 8),
  272.     (kALT_5 >> 8), (kALT_6 >> 8), (kALT_7 >> 8), (kALT_8 >> 8), (kALT_9 >> 8)
  273.   };
  274.   #ifdef CYR
  275.   static char cyr_convert_table[] = {
  276.     (kALT_A >> 8), (kALT_B >> 8), (kALT_W >> 8), (kALT_G >> 8), (kALT_D >> 8),
  277.     (kALT_E >> 8), (kALT_V >> 8), (kALT_Z >> 8), (kALT_I >> 8), (kALT_J >> 8),
  278.     (kALT_K >> 8), (kALT_L >> 8), (kALT_M >> 8), (kALT_N >> 8), (kALT_O >> 8),
  279.     (kALT_P >> 8), (kALT_R >> 8), (kALT_S >> 8), (kALT_T >> 8), (kALT_U >> 8),
  280.     (kALT_F >> 8), (kALT_H >> 8), (kALT_C >> 8), (kALT_BACKAPOST >> 8), (kALT_LBRACKET >> 8),
  281.     (kALT_RBRACKET >> 8), (kALT_Y >> 8), (kALT_X >> 8), (kALT_BACKSLASH >> 8), (kALT_Q >> 8)
  282.   };
  283.   #endif
  284.  
  285.   struct Tkbd_data
  286.   {
  287.     boolean extended_key;
  288.     char last_key;
  289.     void (interrupt far *old_keyboard_handler ) ( void );
  290.   };
  291.  
  292.   #define EXTENDED_KEY kbd_data.extended_key
  293.   #define LAST_KEY kbd_data.last_key
  294.   #define OLD_KEYBOARD_HANDLER kbd_data.old_keyboard_handler
  295.  
  296.   static Tkbd_data kbd_data = { 0, 0 };
  297.  
  298.   #ifdef __386__
  299.   //Dummy function to indicate org of the code to lock
  300.   void keyboard_lock_region_begin( void )
  301.   {
  302.   }
  303.   #endif
  304.  
  305.   static void _loadds interrupt far keyboard_handler( void )
  306.   {
  307.     word *bios_qh = (word *)BIOS_DTA( 0x1C );
  308.     word *bios_qt = (word *)BIOS_DTA( 0x1A );
  309.     word *shifts  = (word *)BIOS_DTA( 0x17 );
  310.     char p, key, sc;
  311.   #ifdef __386__
  312.     static
  313.   #endif
  314.     Tevent ev;
  315.     set_es();
  316.     ev.destination = NULL;
  317.     while( (inp( 0x64 )&0x01)==0 );
  318.     p = (char) inp( 0x60 );
  319.     OLD_KEYBOARD_HANDLER();
  320.     key = (char) ( p & 0x7F );
  321.     ev.SCAN_CODE = key;
  322.     ev.EXT_KEY = EXTENDED_KEY;
  323.     if( ( EXTENDED_KEY = ( p == 0xE0 ) ) != 0 ) return;
  324.     ev.ASCII = 0;
  325.     if( *bios_qh!=*bios_qt )
  326.     {
  327.       ev.ASCII = * ( (word *) BIOS_DTA( *bios_qt ) );
  328.       *bios_qt = *bios_qh;
  329.       switch( lo( ev.ASCII ) )
  330.       {
  331.         case kSPACE:
  332.           if( *shifts & smALT ) ev.ASCII = kALT_SPACE;
  333.           break;
  334.         case kESC:
  335.           if( *shifts & smCTRL ) ev.ASCII = kCTRL_ESC;
  336.           break;
  337.         default:
  338.           sc = hi( ev.ASCII );
  339.           if( ( sc >= 0x47 ) && ( sc <= 0x53 ) &&
  340.               ( sc != 0x4A ) && ( sc != 0x4E ) )
  341.           {
  342.             if( *shifts & smSHIFT )
  343.             {
  344.               lo( ev.ASCII ) = 0;
  345.               ev.ASCII -= 0x4600;
  346.             }
  347.             else
  348.               if( ( *shifts & smNUM ) != smNUM ) lo( ev.ASCII ) = 0;
  349.           }
  350.       }
  351.       if( lo( ev.ASCII ) == 0xE0 )
  352.         lo( ev.ASCII ) = 0;
  353.       else
  354.         if( lo( ev.ASCII ) && ( ev.ASCII!=0x1C0A ) && ( ev.ASCII!=0x0EF0 ) )
  355.           ev.ASCII &= 0x00FF;
  356.     }
  357.     if( p != LAST_KEY )
  358.     {
  359.       LAST_KEY = p;
  360.       ev.code = evKEY_DOWN;
  361.       ev.priority = epKEY_DOWN;
  362.       if( p >= 0x80 )
  363.       {
  364.         ev.code = evKEY_UP;
  365.         ev.priority = epKEY_UP;
  366.       }
  367.       put_event( ev );
  368.     }
  369.     if( ev.ASCII )
  370.     {
  371.       ev.code = evKEY_PRESS;
  372.       ev.priority = epKEY_PRESS;
  373.       put_event( ev );
  374.     }
  375.   }
  376.  
  377.   #ifdef __386__
  378.   //Dummy function to indicate org of the code to lock
  379.   void keyboard_lock_region_end( void )
  380.   {
  381.   }
  382.   #endif
  383.  
  384.   uint get_shifts( void )
  385.   {
  386.     word *shifts = (word *) BIOS_DTA( 0x17 );
  387.     return *shifts;
  388.   }
  389.  
  390.   void put_shifts( uint shift_mask )
  391.   {
  392.     word *shifts = (word *) BIOS_DTA( 0x17 );
  393.     *shifts = (word)shift_mask;
  394.   }
  395.  
  396.   uint get_key( void )
  397.   {
  398.   #ifdef __386__
  399.     static
  400.   #endif
  401.     Tevent ev;
  402.  
  403.     do
  404.     {
  405.       get_event( ev );
  406.     }
  407.     while( ev.code != evKEY_PRESS );
  408.     return ev.ASCII;
  409.   }
  410.  
  411.   boolean pressed( uint key )
  412.   {
  413.   #ifdef __386__
  414.     static
  415.   #endif
  416.     Tevent ev;
  417.  
  418.     do
  419.     {
  420.       get_event( ev );
  421.       if( ev.code == evNOTHING ) return 0;
  422.     }
  423.     while( ( ev.code != evKEY_PRESS ) || ( ev.ASCII != key ) );
  424.     return 1;
  425.   }
  426.  
  427.   uint lat2alt( uint ascii )
  428.   {
  429.     ascii = toupper( ascii );
  430.     if( ( ascii >= 'A' ) && ( ascii <= 'Z' ) )
  431.       return (uint) ( convert_table[ascii-'A'] << 8 );
  432.   #ifdef CYR
  433.     ascii = cyr_toupper( ascii );
  434.     if( ( ascii >= 'Ç' ) && ( ascii <= 'ƒ' ) )
  435.       return (uint) ( cyr_convert_table[ascii-'Ç'] << 8 );
  436.   #endif
  437.     if( ( ascii >= '0' ) && ( ascii <= '9' ) )
  438.       return (uint) ( num_convert_table[ascii-'0'] << 8 );
  439.     return 0;
  440.   }
  441.  
  442.   uint alt2lat( uint ascii )
  443.   {
  444.     word a;
  445.     char *i;
  446.     uint n;
  447.  
  448.     if( !ascii ) return 0;
  449.     if( lo( ascii ) ) return ascii;
  450.     a = (word) ( ascii >> 8 );
  451.     if( ascii == kALT_0 ) return '0';
  452.     if( ( ascii >= kALT_1 ) && ( ascii <= kALT_9 ) ) return (uint) ( a - 0x47 );
  453.     for( i = convert_table, n = 'A'; n <= 'Z' ; n++, i++ )
  454.       if( lo( a ) == *i ) return n;
  455.     return ascii;
  456.   }
  457.  
  458.   #ifdef CYR
  459.   uint alt2cyr( uint ascii )
  460.   {
  461.     word a;
  462.     char *i;
  463.     uint n;
  464.  
  465.     if( !ascii ) return 0;
  466.     if( lo( ascii ) ) return ascii;
  467.     a = (word) ( ascii >> 8 );
  468.     if( ascii == kALT_0 ) return '0';
  469.     if( ( ascii >= kALT_1 ) && ( ascii <= kALT_9 ) ) return (uint) ( a - 0x47 );
  470.     for( i = cyr_convert_table, n = 'Ç'; n <= 'ƒ' ; n++, i++ )
  471.       if( lo( a ) == *i ) return n;
  472.     return ascii;
  473.   }
  474.   #endif
  475.  
  476.   uint upcased( uint ascii )
  477.   {
  478.     if( ( ascii >= 'a' ) && ( ascii <= 'z' ) ) return (uint) ( ascii - 0x20 );
  479.     return ascii;
  480.   }
  481.  
  482.   uint get_shortcut( char *s )
  483.   {
  484.     do
  485.     {
  486.       if( ( s = strchr( s, '|' ) ) == NULL ) return 0;
  487.     }
  488.     while( *(++s) != '~' );
  489.     return lat2alt( *(++s) );
  490.   }
  491.  
  492.  
  493. /*
  494. MOUSE DRIVER
  495. */
  496.   #ifndef NOMOUSE
  497.  
  498.   #define OLD_X mouse_data.old_x
  499.   #define OLD_Y mouse_data.old_y
  500.   #define OLD_HGR_X mouse_data.old_hgr_x
  501.   #define OLD_HGR_Y mouse_data.old_hgr_y
  502.   #define OLD_BUTTONS mouse_data.old_buttons
  503.   #define CODES mouse_data.codes
  504.   #define PRIORITIES mouse_data.priorities
  505.   #define REVERSE mouse_data.reverse
  506.   #define MULTI_CLICK_HANDLE mouse_data.multi_click_handle
  507.   #define REPEAT_HANDLE mouse_data.repeat_handle
  508.   #define CLICK_COUNTER mouse_data.click_counter
  509.  
  510.   #ifndef HGR
  511.  
  512.   #define GRAPH_CHARS mouse_data.graph_chars
  513.   #define MOUSE_ORG_X mouse_data.mouse_org_x
  514.   #define MOUSE_ORG_Y mouse_data.mouse_org_y
  515.   #define OLD_POS_X mouse_data.old_pos_x
  516.   #define OLD_POS_Y mouse_data.old_pos_y
  517.   #define DELTA_X mouse_data.delta_x
  518.   #define DELTA_Y mouse_data.delta_y
  519.   #define SHAPE mouse_data.shape
  520.   #define MASK mouse_data.mask
  521.   #define CBUF mouse_data.cbuf
  522.   #define DBUF mouse_data.dbuf
  523.  
  524.   static word standard_shape14[] =
  525.   {
  526.     0xC000,0xE040,0xF060,0xF870,0xFC78,0xFE7C,0xFF7E,
  527.     0xFE7C,0xFC78,0xFE4C,0xDE0C,0x0F06,0x0F06,0x0F00
  528.   };
  529.   static word standard_shape8[] =
  530.   {
  531.     0xFE00,0xFE7C,0xFC78,0xFC78,0xFE4C,0xCF06,0x0700,
  532.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
  533.   };
  534.  
  535.   static char mouse_hides = 0xFF;
  536.  
  537.   #endif //!HGR
  538.  
  539.   static Tscreen_mode_proc old_mode_proc;
  540.  
  541.   #ifdef __386__
  542.   //Dummy function to indicate org of the code to lock
  543.   void mouse_lock_region_begin( void )
  544.   {
  545.   }
  546.   #endif
  547.  
  548.   #ifndef HGR
  549.  
  550.   static void show_mouse_cursor( void )
  551.   {
  552.     int xx,yy,i;
  553.     uint ofs0, ofs1;
  554.  
  555.     _cli();
  556.     OLD_POS_X = MOUSE_X;
  557.     OLD_POS_Y = MOUSE_Y;
  558.     ofs0 = (uint) ( MOUSE_Y*scr_columns + MOUSE_X );
  559.     ofs1 = (uint) ( ofs0 + scr_columns );
  560.     CBUF[0] = lo( scr_address[ofs0] );
  561.     CBUF[1] = lo( scr_address[ofs1] );
  562.     CBUF[2] = lo( scr_address[ofs0+1] );
  563.     CBUF[3] = lo( scr_address[ofs1+1] );
  564.     open_font_map();
  565.     get_char_def( CBUF[1], get_char_def( CBUF[0], &DBUF[ 0] ) );
  566.     get_char_def( CBUF[3], get_char_def( CBUF[2], &DBUF[32] ) );
  567.     for( i = 0; i < 14; i++ )
  568.     {
  569.       word tmp;
  570.       lo( tmp ) = DBUF[DELTA_Y + i];
  571.       hi( tmp ) = DBUF[DELTA_Y + i + 32];
  572.       tmp = ( rolw( tmp, (char)DELTA_X ) );
  573.       lo( tmp ) &= ~MASK[i];
  574.       lo( tmp ) |= SHAPE[i];
  575.       tmp = ( rorw( tmp, (char)DELTA_X ) );
  576.       DBUF[DELTA_Y + i] = lo( tmp );
  577.       DBUF[DELTA_Y + i + 32] = hi( tmp );
  578.     }
  579.     set_char_def( GRAPH_CHARS[1], set_char_def( GRAPH_CHARS[0], &DBUF[ 0] ) );
  580.     set_char_def( GRAPH_CHARS[3], set_char_def( GRAPH_CHARS[2], &DBUF[32] ) );
  581.     close_font_map();
  582.     xx = (int) ( OLD_POS_X - scr_columns );
  583.     yy = (int) ( OLD_POS_Y - scr_rows );
  584.     lo( scr_address[ofs0] )= GRAPH_CHARS[0];
  585.     if( ++yy ) lo( scr_address[ofs1] ) = GRAPH_CHARS[1];
  586.     if( ++xx )
  587.     {
  588.       lo( scr_address[ofs0+1] ) = GRAPH_CHARS[2];
  589.       if( yy ) lo( scr_address[ofs1+1] ) = GRAPH_CHARS[3];
  590.     }
  591.     _sti();
  592.   }
  593.  
  594.   static void hide_mouse_cursor( void )
  595.   {
  596.     int xx,yy;
  597.     uint ofs0, ofs1;
  598.  
  599.     _cli();
  600.     ofs0 = (uint) ( OLD_POS_Y*scr_columns + OLD_POS_X );
  601.     ofs1 = (uint) ( ofs0 + scr_columns );
  602.     xx = (int) ( OLD_POS_X - scr_columns );
  603.     yy = (int) ( OLD_POS_Y - scr_rows );
  604.     lo( scr_address[ofs0] ) = CBUF[0];
  605.     if( ++yy ) lo( scr_address[ofs1] ) = CBUF[1];
  606.     if( ++xx )
  607.     {
  608.       lo( scr_address[ofs0+1] ) = CBUF[2];
  609.       if( yy ) lo( scr_address[ofs1+1] ) = CBUF[3];
  610.     }
  611.     _sti();
  612.   }
  613.  
  614.   static void update_pos( int rel_x, int rel_y )
  615.   {
  616.     uint x_pixels, y_pixels;
  617.  
  618.     _cli();
  619.     x_pixels = (uint) ( scr_columns*8 - 1 );
  620.     y_pixels = (uint) ( scr_rows*scr_char_size - 1 );
  621.     rel_x += MOUSE_ORG_X;
  622.     rel_y += MOUSE_ORG_Y;
  623.     if( rel_x < 0 )
  624.     {
  625.       MOUSE_ORG_X -= rel_x;
  626.       rel_x = 0;
  627.     }
  628.     else
  629.       if( rel_x > x_pixels )
  630.       {
  631.         MOUSE_ORG_X -= ( rel_x - x_pixels );
  632.         rel_x = x_pixels;
  633.       }
  634.     if( rel_y < 0 )
  635.     {
  636.       MOUSE_ORG_Y -= rel_y;
  637.       rel_y = 0;
  638.     }
  639.     else
  640.       if( rel_y > y_pixels )
  641.       {
  642.         MOUSE_ORG_Y -= ( rel_y - y_pixels );
  643.         rel_y = y_pixels;
  644.       }
  645.     DELTA_X = (int) ( rel_x & 7 );
  646.     DELTA_Y = (int) ( rel_y % scr_char_size );
  647.     MOUSE_X = (int) ( rel_x >> 3 );
  648.     MOUSE_Y = (int) ( rel_y / scr_char_size );
  649.     _sti();
  650.   }
  651.  
  652.   #endif //!HGR
  653.  
  654.   static void auto_repeat( void )
  655.   {
  656.   #ifdef __386__
  657.     static
  658.   #endif
  659.     Tevent ev;
  660.  
  661.     ev.code = evMOUSE_REP;
  662.     ev.priority = epMOUSE_REP;
  663.     ev.destination = NULL;
  664.     ev.GLOBAL_X = MOUSE_X;
  665.     ev.GLOBAL_Y = MOUSE_Y;
  666.   #ifdef HGR
  667.     ev.GLOBAL_HGR_X = MOUSE_HGR_X;
  668.     ev.GLOBAL_HGR_Y = MOUSE_HGR_Y;
  669.   #endif
  670.     ev.BUTTONS = MOUSE_BUTTONS;
  671.     ev.CLICKS = 0;
  672.     put_event( ev );
  673.     call_request( REPEAT_HANDLE, auto_repeat, REPEAT_TIME );
  674.   }
  675.  
  676.   static void clear_multi_click( void )
  677.   {
  678.     CLICK_COUNTER = 0;
  679.   }
  680.  
  681.   /*
  682.     On entry:
  683.       AX - event bit MASK
  684.       BX - buttons status: bit 0 - left, bit 1 - right, bit 2 - center
  685.       CX - x (divide by 8 )
  686.       DX - y (divide by 8 )
  687.       SI - x rel distance
  688.       DI - y rel distance
  689.   */
  690.   void _loadds far mouse_handler( int max, int mbx, int mcx, int mdx, int msi, int mdi )
  691.   {
  692.     uint events, buttons;
  693.     int x, y, rel_x, rel_y, i;
  694.   #ifdef __386__
  695.     static
  696.   #endif
  697.     Tevent ev;
  698.     _cld();
  699.     events = (uint)((word)max);
  700.     buttons = (uint)((word)mbx);
  701.     x = (int)((short)mcx);
  702.     y = (int)((short)mdx);
  703.     rel_x = (int)((short)msi);
  704.     rel_y = (int)((short)mdi);
  705.     ev.destination = NULL;
  706.     _cli();
  707.     set_es();
  708.     buttons &= 7;
  709.     if( !MOUSE_ENABLED ) goto _return;
  710.   #ifndef HGR
  711.     if( GRAPH_CURSOR)
  712.     {
  713.       update_pos( rel_x, rel_y );
  714.       if( !mouse_hides )
  715.       {
  716.         hide_mouse_cursor();
  717.         show_mouse_cursor();
  718.       }
  719.     }
  720.     else
  721.   #endif
  722.     {
  723.   #ifdef HGR
  724.       MOUSE_HGR_X = x;
  725.       MOUSE_HGR_Y = y;
  726.       MOUSE_X = (int) ( x >> 3 );
  727.       MOUSE_Y = (int) ( y >> 4 );
  728.   #else
  729.       MOUSE_X = (int) ( x >> 3 );
  730.       MOUSE_Y = (int) ( y >> 3 );
  731.   #endif
  732.     }
  733.     if( events==1 &&
  734.   #ifdef HGR
  735.           OLD_HGR_X==MOUSE_HGR_X && OLD_HGR_Y==MOUSE_HGR_Y ) goto _return;
  736.     ev.GLOBAL_HGR_X = MOUSE_HGR_X;
  737.     ev.GLOBAL_HGR_Y = MOUSE_HGR_Y;
  738.   #else
  739.           OLD_X==MOUSE_X && OLD_Y==MOUSE_Y ) goto _return;
  740.   #endif
  741.     ev.GLOBAL_X = MOUSE_X;
  742.     ev.GLOBAL_Y = MOUSE_Y;
  743.     if( REVERSE_BUTTONS ) buttons = REVERSE[buttons];
  744.     ev.BUTTONS = MOUSE_BUTTONS = (char) buttons;
  745.     if( buttons != OLD_BUTTONS )
  746.     {
  747.       cancel_request( REPEAT_HANDLE );
  748.       ev.BUTTON = ( ( OLD_BUTTONS&1 ) == ( buttons&1 ) );
  749.       OLD_BUTTONS = buttons;
  750.     }
  751.     for( i = 0; i < 7; i++ )
  752.       if( events & (1 << i ) )
  753.       {
  754.         ev.code = CODES[i];
  755.         switch( ev.code )
  756.         {
  757.           case evMOUSE_MOVE:
  758.           {
  759.             CLICK_COUNTER = 0;
  760.   #ifdef HGR
  761.             if( OLD_X==MOUSE_X && OLD_Y==MOUSE_Y )
  762.               if( buttons )
  763.                 ev.code=evMOUSE_HGR_DRAG;
  764.               else
  765.                 ev.code=evMOUSE_HGR_MOVE;
  766.             else
  767.   #endif
  768.               if( buttons ) ev.code=evMOUSE_DRAG;
  769.             break;
  770.           }
  771.           case evMOUSE_DOWN:
  772.           {
  773.             ev.CLICKS = CLICK_COUNTER++;
  774.             cancel_request( MULTI_CLICK_HANDLE );
  775.             cancel_request( REPEAT_HANDLE );
  776.             call_request( REPEAT_HANDLE, auto_repeat, REPEAT_WAIT_TIME );
  777.             call_request( MULTI_CLICK_HANDLE, clear_multi_click, MULTI_CLICK_TIME );
  778.             break;
  779.           }
  780.         }
  781.         ev.priority = PRIORITIES[i];
  782.         put_event( ev );
  783.       }
  784.     OLD_X = MOUSE_X;
  785.     OLD_Y = MOUSE_Y;
  786.   #ifdef HGR
  787.     OLD_HGR_X = MOUSE_HGR_X;
  788.     OLD_HGR_Y = MOUSE_HGR_Y;
  789.   #endif
  790.     _return: _sti();
  791.   }
  792.   #ifdef __386__
  793.   #pragma aux mouse_handler parm [EAX] [EBX] [ECX] [EDX] [ESI] [EDI]
  794.   #else
  795.   #pragma aux mouse_handler parm  [AX]  [BX]  [CX]  [DX]  [SI]  [DI]
  796.   #endif
  797.  
  798.   #ifdef __386__
  799.   //Dummy function to indicate end of the code to lock
  800.   void mouse_lock_region_end( void )
  801.   {
  802.   }
  803.   #endif
  804.  
  805.   #ifndef HGR
  806.  
  807.   void graph_mouse( boolean enable )
  808.   {
  809.     union REGS r;
  810.  
  811.     if( !BUTTONS_COUNT || !scr_soft_fonts ) return;
  812.     _cli();
  813.     hide_mouse();
  814.     if( (GRAPH_CURSOR=enable)==0 )
  815.     {
  816.       r.w.cx = (word) ( MOUSE_X << 3 );
  817.       r.w.dx = (word) ( MOUSE_Y << 3 );
  818.       r.w.ax = 4;
  819.       INTR( 0x33, &r, &r );
  820.     }
  821.     show_mouse();
  822.     _sti();
  823.   }
  824.  
  825.   void set_graph_cursor( word *def )
  826.   {
  827.     uint i;
  828.     char *p;
  829.  
  830.     if( !BUTTONS_COUNT ) return;
  831.     _cli();
  832.     hide_mouse();
  833.     if( def == NULL )
  834.       if( scr_char_size == 8 )
  835.         def = standard_shape8;
  836.       else
  837.         def = standard_shape14;
  838.     p = (char * ) def;
  839.     for( i=0; i < 14; i++ )
  840.     {
  841.       SHAPE[i] = *(p++ );
  842.       MASK[i] = *(p++ );
  843.     }
  844.     show_mouse();
  845.     _sti();
  846.   }
  847.  
  848.   #endif //!HGR
  849.  
  850.   void hide_mouse( void )
  851.   {
  852.     union REGS r;
  853.  
  854.     if( BUTTONS_COUNT )
  855.   #ifndef HGR
  856.       if( !GRAPH_CURSOR )
  857.   #endif
  858.       {
  859.         r.w.ax = 2;
  860.         INTR( 0x33, &r, &r );
  861.       }
  862.   #ifndef HGR
  863.       else
  864.         if( !mouse_hides-- ) hide_mouse_cursor();
  865.   #endif
  866.   }
  867.  
  868.   void show_mouse( void )
  869.   {
  870.     union REGS r;
  871.  
  872.     if( BUTTONS_COUNT )
  873.   #ifndef HGR
  874.       if( !GRAPH_CURSOR )
  875.   #endif
  876.       {
  877.         r.w.ax = 1;
  878.         INTR( 0x33, &r, &r );
  879.       }
  880.   #ifndef HGR
  881.       else
  882.         if( !++mouse_hides ) show_mouse_cursor();
  883.   #endif
  884.   }
  885.  
  886.   void mouse_goto_xy( int x, int y )
  887.   {
  888.     union REGS r;
  889.  
  890.     if( BUTTONS_COUNT )
  891.     {
  892.       hide_mouse();
  893.       MOUSE_X = x;
  894.       MOUSE_Y = y;
  895.   #ifdef HGR
  896.       MOUSE_HGR_X = (int) ( x << 3 );
  897.       MOUSE_HGR_Y = (int) ( y << 3 );
  898.   #else
  899.       MOUSE_ORG_X = (int) ( x << 3 );
  900.       MOUSE_ORG_Y = (int) ( y * scr_char_size );
  901.   #endif
  902.       r.w.cx = (word) ( MOUSE_X << 3 );
  903.       r.w.dx = (word) ( MOUSE_Y << 3 );
  904.       r.w.ax = 4;
  905.       INTR( 0x33, &r, &r );
  906.   #ifndef HGR
  907.       if( GRAPH_CURSOR ) update_pos(0, 0 );
  908.   #endif
  909.       show_mouse();
  910.     }
  911.   }
  912.  
  913.   void get_mouse_speed( uint &sx, uint &sy )
  914.   {
  915.     union REGS r;
  916.  
  917.     if( BUTTONS_COUNT )
  918.     {
  919.       r.w.bx = 0;
  920.       r.w.cx = 0;
  921.       r.w.ax = 0x1B;
  922.       INTR( 0x33, &r, &r );
  923.       sx = r.w.bx;
  924.       sy = r.w.cx;
  925.     }
  926.   }
  927.  
  928.   void set_mouse_speed( uint sx, uint sy )
  929.   {
  930.     union REGS r;
  931.  
  932.     if( BUTTONS_COUNT )
  933.     {
  934.       r.w.ax = 0x1B;
  935.       INTR( 0x33, &r, &r );
  936.       r.w.bx = (word)sx;
  937.       r.w.cx = (word)sy;
  938.       r.w.ax = 0x1A;
  939.       INTR( 0x33, &r, &r );
  940.     }
  941.   }
  942.  
  943.   #ifndef HGR
  944.  
  945.   void set_mouse_mask( uint and_mask, uint or_mask )
  946.   {
  947.     union REGS r;
  948.  
  949.     if( BUTTONS_COUNT )
  950.     {
  951.       r.w.bx = 0;
  952.       r.w.cx = (word)and_mask;
  953.       r.w.dx = (word)or_mask;
  954.       r.w.ax = 0x0A;
  955.       INTR( 0x33, &r, &r );
  956.     }
  957.   }
  958.  
  959.   void set_mouse_chars( char *gc )
  960.   {
  961.     _cli();
  962.     hide_mouse();
  963.     restore_chars_def();
  964.     memcpy(GRAPH_CHARS,gc,4 );
  965.     save_chars_def();
  966.     show_mouse();
  967.     _sti();
  968.   }
  969.  
  970.   static char chars_def[4*16];
  971.  
  972.   void save_chars_def( void )
  973.   {
  974.     char *ptr;
  975.     int i;
  976.  
  977.     if( BUTTONS_COUNT && GRAPH_CURSOR )
  978.     {
  979.       open_font_map();
  980.       for( ptr = chars_def, i = 0; i < 4; i++ )
  981.         ptr = get_char_def( GRAPH_CHARS[i], ptr );
  982.       close_font_map();
  983.     }
  984.   }
  985.  
  986.   void restore_chars_def( void )
  987.   {
  988.     char *ptr;
  989.     int i;
  990.  
  991.     if( BUTTONS_COUNT && GRAPH_CURSOR )
  992.     {
  993.       open_font_map();
  994.       for( ptr = chars_def, i = 0; i < 4; i++ )
  995.         ptr = set_char_def( GRAPH_CHARS[i], ptr );
  996.       close_font_map();
  997.     }
  998.   }
  999.  
  1000.   #endif //!HGR
  1001.  
  1002.   static void mode_proc( char mode, char char_size )
  1003.   {
  1004.     uint old_scr_rows, old_scr_cols;
  1005.  
  1006.     old_scr_rows = scr_rows;
  1007.     old_scr_cols = scr_columns;
  1008.     hide_mouse();
  1009.     old_mode_proc( mode, char_size );
  1010.     mouse_goto_xy( (int) ( MOUSE_X*scr_columns/old_scr_cols ),
  1011.                    (int) ( MOUSE_Y*scr_rows/old_scr_rows    ) );
  1012.   #ifndef HGR
  1013.     set_graph_cursor( NULL );
  1014.   #endif
  1015.     show_mouse();
  1016.   }
  1017.  
  1018.  
  1019. /*
  1020. STARTUP & EXIT
  1021. */
  1022.   #ifndef NOCONFIG
  1023.   static void read_params( void )
  1024.   {
  1025.     long x;
  1026.  
  1027.     seek_section( 0, SECTION_MOUSE );
  1028.     ini( VAR_SENSITIVITY, x, 0 ); if( x ) set_mouse_speed( x, x );
  1029.     ini( VAR_MULTI_CLICK, MULTI_CLICK_TIME, MULTI_CLICK_TIME );
  1030.     ini( VAR_MOUSE_DELAY, REPEAT_WAIT_TIME, REPEAT_WAIT_TIME );
  1031.     ini( VAR_MOUSE_SPEED, REPEAT_TIME, REPEAT_TIME );
  1032.     ini_lnerr( !MULTI_CLICK_TIME || !REPEAT_WAIT_TIME || !REPEAT_TIME, INIERR_RANGE );
  1033.   #ifndef HGR
  1034.     ini( VAR_GRAPH, GRAPH_CURSOR, GRAPH_CURSOR );
  1035.   #endif
  1036.   }
  1037.   #endif
  1038.   #endif //NOMOUSE
  1039.  
  1040.   void hook_drivers( void )
  1041.   {
  1042.     OLD_TIMER_HANDLER = _dos_getvect( TIMER_INTR );
  1043.     _dos_setvect( TIMER_INTR, timer_handler );
  1044.     OLD_KEYBOARD_HANDLER = _dos_getvect( KBD_INTR );
  1045.     _dos_setvect( KBD_INTR, keyboard_handler );
  1046.   #ifndef NOMOUSE
  1047.     union REGS r;
  1048.     struct SREGS sr;
  1049.  
  1050.     BUTTONS_COUNT = 0;
  1051.     r.w.ax = 0;
  1052.     INTR( 0x33, &r, &r );
  1053.     if( r.w.ax )
  1054.     {
  1055.       BUTTONS_COUNT = (char ) r.w.bx;
  1056.       r.w.ax = 4;
  1057.       r.w.cx = r.w.dx = 0;
  1058.   #ifndef HGR
  1059.       MOUSE_ORG_X = MOUSE_ORG_Y = 0;
  1060.   #endif
  1061.       INTR( 0x33, &r, &r );
  1062.   #ifndef HGR
  1063.       GRAPH_CURSOR = GRAPH_CURSOR && ( scr_mode != 7 );
  1064.       save_chars_def();
  1065.   #endif
  1066.       r.w.ax = 0x0C;
  1067.       r.w.cx = 0x7F;
  1068.   #ifdef __386__
  1069.       r.x.edx = FP_OFF( mouse_handler );
  1070.   #else
  1071.       r.w.dx = FP_OFF( mouse_handler );
  1072.   #endif
  1073.       segread( &sr );
  1074.       sr.es = FP_SEG( mouse_handler );
  1075.       INTRX( 0x33, &r, &r, &sr );
  1076.       r.w.cx = 0;
  1077.       r.w.dx = (word) ( (scr_columns - 1 ) << 3 );
  1078.       r.w.ax = 7;
  1079.       INTR( 0x33, &r, &r );
  1080.       r.w.dx = (word) ( (scr_rows - 1 ) << 3 );
  1081.       r.w.ax = 8;
  1082.       INTR( 0x33, &r, &r );
  1083.   #ifndef HGR
  1084.       set_graph_cursor( NULL );
  1085.   #endif
  1086.       r.w.cx = 0xFF;
  1087.       r.w.dx = 0xA000;
  1088.       r.w.bx = 0;
  1089.       r.w.ax = 0x0A;
  1090.       INTR( 0x33, &r, &r );
  1091.       mouse_goto_xy( 0, 0 );
  1092.     }
  1093.   #endif //NOMOUSE
  1094.   }
  1095.  
  1096.   void unhook_drivers( void )
  1097.   {
  1098.     _dos_setvect( TIMER_INTR, OLD_TIMER_HANDLER );
  1099.     _dos_setvect( KBD_INTR, OLD_KEYBOARD_HANDLER );
  1100.   #ifndef NOMOUSE
  1101.     union REGS r;
  1102.     struct SREGS sr;
  1103.  
  1104.     if( BUTTONS_COUNT )
  1105.     {
  1106.       r.w.ax = 0x0C;
  1107.       segread( &sr );
  1108.       r.w.cx = r.w.dx = sr.es = 0;
  1109.       INTRX( 0x33, &r, &r, &sr );
  1110.   #ifndef HGR
  1111.       restore_chars_def();
  1112.   #endif
  1113.     }
  1114.   #endif
  1115.   }
  1116.  
  1117.   static void __tini_drivers( void )
  1118.   {
  1119.   #ifndef NOMOUSE
  1120.     hide_mouse();
  1121.   #endif
  1122.     unhook_drivers();
  1123.   }
  1124.  
  1125.   void __init_drivers( void )
  1126.   {
  1127.   #ifdef __FLAT__
  1128.     unsigned long *system_timer = (unsigned long *) BIOS_DTA( 0x6C );
  1129.   #else
  1130.     unsigned long far *system_timer = (unsigned long *) BIOS_DTA( 0x6C );
  1131.   #endif
  1132.  
  1133.   #ifdef __386__
  1134.     lock_region( &events_data, sizeof( events_data ) );
  1135.     lock_region( (void near *) events_lock_region_begin,
  1136.                    (char *) events_lock_region_end -
  1137.                    (char *) events_lock_region_begin );
  1138.     lock_region( &timer_data, sizeof( timer_data ) );
  1139.     lock_region( (void near *) timer_lock_region_begin,
  1140.                    (char *) timer_lock_region_end -
  1141.                    (char *) timer_lock_region_begin );
  1142.     lock_region( &kbd_data, sizeof( kbd_data ) );
  1143.     lock_region( (void near *) keyboard_lock_region_begin,
  1144.                    (char *) keyboard_lock_region_end -
  1145.                    (char *) keyboard_lock_region_begin );
  1146.   #ifndef NOMOUSE
  1147.     lock_region( &mouse_data, sizeof( mouse_data ) );
  1148.     lock_region( (void near *) mouse_lock_region_begin,
  1149.                    (char *) mouse_lock_region_end -
  1150.                    (char *) mouse_lock_region_begin );
  1151.   #endif
  1152.   #endif
  1153.   #ifndef NOMOUSE
  1154.     REPEAT_HANDLE = alloc_timer();
  1155.     MULTI_CLICK_HANDLE = alloc_timer();
  1156.   #endif
  1157.  
  1158.   //init events
  1159.     do
  1160.     {
  1161.       OLD_TIMER = *system_timer;
  1162.     }
  1163.     while( OLD_TIMER != *system_timer );
  1164.  
  1165.   //init timer
  1166.     for( uint i = 0; i < MAX_TIMERS; i++ )
  1167.       COUNTERS[i] = 0;
  1168.  
  1169.     hook_drivers();
  1170.  
  1171.   //init mouse
  1172.   #ifndef NOMOUSE
  1173.     if( BUTTONS_COUNT )
  1174.     {
  1175.       old_mode_proc = hook_mode_proc( mode_proc );
  1176.   #ifndef NOCONFIG
  1177.       read_params();
  1178.   #endif
  1179.   #if !defined( NOPARAM ) && !defined( HGR )
  1180.       if( param_opt( "/M+" ) ) GRAPH_CURSOR = scr_soft_fonts;
  1181.       if( param_opt( "/M-" ) ) GRAPH_CURSOR = 0;
  1182.   #endif
  1183.     }
  1184.   #endif //NOMOUSE
  1185.     atexit( __tini_drivers );
  1186.   }
  1187.